package com.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import java.awt.*;
import java.io.*;
import java.util.Random;

/**
 * AES加密、解密工具类
 */
public class AESUtil {

    /*
     * 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式，key需要为16位。
     * key是aes的一个加密源，也就是通过该key加密后，必须通过该key就进行解密；对数据不是特别敏感的，直接用静态的key即可；
     * 有些场景下数据异常敏感，那么这个key就要动态生成，结合RSA进行加密，，就能做到每次请求，key都不一样，安全程度大大加强；
     * 当然key可以为32，但是要下载两个jdk的jar包，好像是美国那边没有发出来这个jar，具体的key百度下
     */
    public static String 默认密钥 = "jtskdjfkxqsvwwsk";
    public static String 密钥 = 默认密钥;

    /**
     * 偏移量，随便给一个就可以了，不给也行
     */
    public static String 默认偏移量 = "jtskdjfkxqsvwwsk";
    public static String 偏移量 = 默认偏移量;

    /**
     * 分隔符
     */
    public static final String separate = "ZmhzeGZsd2I=";

    public static String 登录密码 = "";
    public static String 密文 = "";

    /**
     * 加密
     * @param str 要加密的字符串
     * @param flag 是否使用默认密钥和偏移量进行加密
     */
    public static String encrypt(String str,boolean flag) {
        int length = 登录密码.length();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            if (!flag){
                密钥 = 登录密码 + generateRandom(16-length); // 随机生成密钥
                偏移量 = 登录密码 + generateRandom(16-length); // 获取偏移量
            }else {
                密钥 = 登录密码 + 默认密钥.substring(0,16-length);
                偏移量 = 登录密码 + 默认偏移量.substring(0,16-length);
            }
            //System.out.println("加密密钥和偏移量："+密钥+"\t"+偏移量);
            SecretKeySpec skeySpec = new SecretKeySpec(密钥.getBytes(), "AES");
            IvParameterSpec ivp = new IvParameterSpec(偏移量.getBytes());// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivp);
            byte[] encrypted = cipher.doFinal(str.getBytes("utf-8"));
            return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码。
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     * @param str 要解密的字符串
     * @param raw 密钥
     * @param ivStr 偏移量
     */
    public static String decrypt(String str,String raw,String ivStr){
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(raw.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivStr.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(str);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 写入到txt文件
     * @param path   文件路径
     * @param start 内容开头
     * @param content 内容
     */
    public static void 写入内容(String path,String start,String content) {
        BufferedWriter out = null;
        BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();
        try {
            File file = new File(path);
            if (!file.exists()){
                file.createNewFile();
            }
            String str = "";
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            while((str = reader.readLine())!=null){
                if (isNotBlank(start) && str.startsWith(start)){ // 替换旧内容
                    sb.append(content).append("\n");
                }else {
                    sb.append(str).append("\n");
                }
            }
            str = sb.toString();
            if (!str.contains(content)){ // 追加新内容
                sb.append(content).append("\n");
            }
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
            out.write(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String 读取登录密码(String path) {
        BufferedReader reader = null;
        String str = "";
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
            while((str = reader.readLine())!=null){
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        密文 = str;
        return str;
    }

    /**
     * 根据指定长度随机生成字符串
     */
    public static String generateRandom(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; ++i) {
            int number = random.nextInt(str.length());
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

    public static boolean isNotBlank(String str){
        if (str == null || str.length() == 0){
            return false;
        }
        return true;
    }

    public static boolean isNull(String str){
        if (str == null || str.length() == 0){
            return true;
        }
        return false;
    }

    /**
     * 提示框
     */
    public static void tips(String str){
        UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("宋体", Font.ITALIC, 16)));
        JOptionPane.showMessageDialog(null, str);
    }

}
